package com.sinaapp.gavinzhang.GSpider.config;

import com.caucho.hessian.client.HessianRuntimeException;
import com.caucho.hessian.server.HessianServlet;
import com.sinaapp.gavinzhang.GSpider.common.IpUtil;
import com.sinaapp.gavinzhang.GSpider.common.RegisterUtil;
import com.sinaapp.gavinzhang.GSpider.common.ServletUtil;
import com.sinaapp.gavinzhang.GSpider.management.Register;
import com.sinaapp.gavinzhang.GSpider.management.RegistrationCenter;
import com.sinaapp.gavinzhang.GSpider.management.Stub;
import com.sinaapp.gavinzhang.GSpider.process.ProcessorDispatcher;
import com.sinaapp.gavinzhang.GSpider.webaddress.URLDispatcher;
import com.sinaapp.gavinzhang.GSpider.webaddress.WebAddress;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @author gavin
 * @version 1.0
 * @date 2016/4/9
 * @description 控制台式的配置状态管理器
 */
public class ConfigConsoleManagement extends HessianServlet implements ConfigDispatcher {
    private static final Logger logger = LoggerFactory.getLogger(ConfigConsoleManagement.class);
    private static final Logger htmlLogger = LoggerFactory.getLogger("com.sinaapp.gavinzhang.GSpider.http.servlet.ConfigConsoleManagement.html");

    public static final int DEFAULT_PORT = 20003;

    public static String centerIp;
    public static int centerPort;

    public final static Stub configStub = Stub.newStub();

    public static PageProcessorConfig pageProcessorConfig;

    public static WebAddress initWebAddress;

    @Override
    public PageProcessorConfig getPageProcessorConfig() {
        return pageProcessorConfig;
    }

    @Override
    public void info(String message) {
        htmlLogger.info(message);
    }

    @Override
    public void warn(String message) {
        htmlLogger.warn(message);
    }

    @Override
    public void error(String message) {
        htmlLogger.error(message);
    }

    @Override
    public int echo() {
        return HEARTECHO;
    }

    @Override
    public void shutdown() {
        System.exit(HEARTECHO);
    }

    public static String getStatus()throws Exception{
        String configHtml = "网址管理器数量:${urlDispatcherSize}\n" +
                "网址管理器待抓取网址数量:${pendingSize}\n" +
                "网址管理器已抓取网址数量:${visitedSize}\n"+
                "抓取集群数量:${processorDispatcherSize}\n" +
                "${status}\n";
        Register center = RegisterUtil.getRegister(centerIp, centerPort, RegistrationCenter.REGISTRATIONCENTER);

        List<Stub> stubs = new ArrayList<>();
        try {
            stubs = center.getURLDispatchers();
        } catch (Exception e) {
            logger.error("注册中心连接超时!" + centerIp + ":" + centerPort);
            return null;
        }
        int pendingSize = 0;
        int visitedSize = 0;
        for (Stub s : stubs) {
            if (s.equals(Stub.getNoneStub())) {
                logger.warn("找不到网址管理器");
            } else {
                URLDispatcher urlDispatcher = (URLDispatcher) RegisterUtil.getHessianServer(URLDispatcher.class, s.getName());
                pendingSize += urlDispatcher.pendingSize();
                visitedSize += urlDispatcher.visitedSize();
            }
        }
        configHtml = configHtml.replace("${urlDispatcherSize}", String.valueOf(stubs.size()));
        configHtml = configHtml.replace("${pendingSize}", String.valueOf(pendingSize));
        configHtml = configHtml.replace("${visitedSize}", String.valueOf(visitedSize));

        try {
            stubs = center.getProcessorDispatchers();
        } catch (HessianRuntimeException e) {
            logger.error("注册中心连接超时!" + centerIp + ":" + centerPort);
            return null;
        }
        String status = "";
        for (Stub s : stubs) {
            if (s.equals(Stub.getNoneStub())) {
                logger.warn("找不到抓取集群管理器");
            } else {
                ProcessorDispatcher processorDispatcher = (ProcessorDispatcher) RegisterUtil.getHessianServer(ProcessorDispatcher.class, s.getName());
                status += s.getName() + processorDispatcher.getStatus() + "<br>";
            }
        }
        configHtml = configHtml.replace("${processorDispatcherSize}", String.valueOf(stubs.size()));
        configHtml = configHtml.replace("${status}", status.replace("<br>","\n").replace("<p>","").replace("</p>",""));
        return configHtml;
    }

    private static void command(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                Scanner sc = new Scanner(System.in);
                while (true){
                    try {
                        if (sc.hasNext()){
                            String s = sc.nextLine();
                            if (s.equals("status")){
                                System.out.println(getStatus());
                            }
                        }
                    }catch (Exception e){

                    }
                }
            }
        }).start();
    }

    private static void pushConfig(){
        logger.info("注册配置文件");
        if (pageProcessorConfig == null) {
            logger.error("配置文件没有配置!");
            System.exit(-1);
        }

        try {
            Register center = RegisterUtil.getRegister(centerIp, centerPort, RegistrationCenter.REGISTRATIONCENTER);

            //分发数据
            List<Stub> stubs = center.getURLDispatchers();
            for (Stub s : stubs) {
                URLDispatcher urlDispatcher = (URLDispatcher) RegisterUtil.getHessianServer(URLDispatcher.class, s.getName());
                urlDispatcher.add(initWebAddress);
            }
            if (stubs.size() == 0) {
                logger.warn("找不到网址管理器");
                System.exit(-2);
            }

            //最新配置分发到抓取集群中
            stubs = center.getProcessorDispatchers();
            for (Stub s : stubs) {
                ProcessorDispatcher processorDispatcher = (ProcessorDispatcher) RegisterUtil.getHessianServer(ProcessorDispatcher.class, s.getName());
                processorDispatcher.setPageProcessorConfig(pageProcessorConfig);
            }
            if (stubs.size() == 0) {
                logger.warn("找不到抓取集群管理器");
            }

        } catch (Exception e) {
            logger.error("注册失败！" + centerIp + ":" + centerPort, e);
            System.exit(-1);
        }
        logger.info("注册配置文件完成");
    }

    public static void setUp() throws Exception {
        logger.warn("注册中心IP为:(默认)" + IpUtil.getRealIp());
        setUp(IpUtil.getRealIp());
    }

    public static void setUp(String ip) throws Exception {
        logger.warn("注册中心端口号为:(默认)" + RegistrationCenter.DEFAULT_PORT);
        setUp(ip, RegistrationCenter.DEFAULT_PORT);
    }

    public static void setUp(int localPort)throws Exception{
        logger.warn("注册中心IP为:(默认)" + IpUtil.getRealIp());
        logger.warn("注册中心端口号为:(默认)" + RegistrationCenter.DEFAULT_PORT);
        setUp(IpUtil.getRealIp(),RegistrationCenter.DEFAULT_PORT,localPort);
    }


    public static void setUp(String ip, int port) throws Exception {
        logger.warn("配置状态管理器端口号为:(默认)" + ConfigConsoleManagement.DEFAULT_PORT);
        setUp(ip, port, ConfigConsoleManagement.DEFAULT_PORT);
    }

    public static void setUp(String ip, int port, int localPort) throws Exception {
        logger.info("注册中心IP为:"+ip);
        logger.info("注册中心端口号为:"+port);
        logger.info("配置状态管理器端口号为:"+localPort);
        centerIp = ip;
        centerPort = port;

        //得到管理中心
        logger.info("获取注册中心服务");
        Register center = RegisterUtil.getRegister(ip, port, RegistrationCenter.REGISTRATIONCENTER);

        //注册服务
        logger.info("注册配置状态管理器");
        String name = "http://" + IpUtil.getRealIp() + ":" + localPort + "/" + RegistrationCenter.CONFIGDISPATCHER + "." + configStub.getToken();
        configStub.setName(name);
        logger.info("注册中..."+configStub);
        try {
            if (center.Registrate(configStub).equals(Stub.getNoneStub())) {
                logger.error("注册失败!");
                System.exit(-1);
            }
        }catch (HessianRuntimeException e){
            logger.error("注册中心连接超时!"+centerIp+":"+centerPort);
            System.exit(-1);
        }

        logger.info("注册成功!");

        //启动jetty服务
        Server server = new Server(localPort);
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        server.setHandler(context);
        logger.info("GServer 启动中...");
        ServletUtil.addServlet(context, ConfigConsoleManagement.class, "/" + RegistrationCenter.CONFIGDISPATCHER + "." + configStub.getToken());
        logger.info("GServer 添加RPC网址管理服务成功!");
        server.start();
        logger.info("GServer 地址: " + server.getURI().toString());
        logger.info("GServer 启动成功!" + server.getState());
        pushConfig();
        command();
        //server.join();
    }

    public static void main(String[] args)throws Exception{
        ConfigConsoleManagement.setUp();
    }
}
